<?php


namespace Wunder\Esorm\Handler;

use Elasticsearch\Client;
use Swoft\Bean\Annotation\Mapping\Bean;
use Wunder\Esorm\Eloquent\Builder;

/**
 * @Bean()
 * Class Collection
 * @package Wunder\Esorm\Handler
 */
class Collection
{

    /**
     * @var Client
     */
    private $elasticsearch;

    /**
     * @var Builder
     */
    private $builder = null;

    /**
     * @var string
     */
    private $index;

    /**
     * @var int
     */
    private $size = 10;

    /**
     * @var int
     */
    private $form = 0;

    /**
     * @var array
     */
    private $_source = [];

    /**
     * @var array
     */
    private $sort = [];

    /**
     * @var int
     */
    private $total = 0;

    /**
     * @var array
     */
    private $list = [];

    public function setClient(Client $client){
        $this->elasticsearch = $client;
    }

    public function __call($name, $arguments)
    {
        $this->builder->$name(...$arguments);
        return $this;
    }

    public function Index(string $index)
    {
        $this->index = $index;
        if(!$this->builder){
            $this->builder = new Builder();
        }
        return $this;
    }
    /**
     * @return $this
     */
    public function query(string $index="")
    {
        if($index){
            $this->index = $index;
        }
        if(!$this->builder){
            $this->builder = new Builder();
        }
        return $this;
    }

    public function list(array $source = []):array
    {
        if($source) $this->_source = $source;

        $list = $this->result($this->builder->getQuery());

        return [
            "total"=>$this->total,
            "page"=>($this->form /  $this->size) + 1,
            "size"=>$this->size,
            "total_page"=> ceil($this->total / $this->size),
            "list" => $list
        ];
    }

    public function get(array $source = []):array
    {
        if($source) $this->_source = $source;

        return $this->result($this->builder->getQuery());
    }

    public function first(array $source = []):array
    {
        if($source) $this->_source = $source;

        $list = $this->result($this->builder->getQuery());
        if(!empty($list)){
            return $list[0];
        }
        return [];
    }

    public function find($id="", array $source = []):array
    {
        if(!empty($id)){
            $this->builder->Ids([$id]);
        }
        return [];
    }

    public function size(int $size)
    {
        $this->size = $size;
        return $this;
    }

    public function sort(array $sorts)
    {
        $so = [];
        foreach ($sorts as $key=>$sort){
            if($sort == "random"){
                $so[] = [
                    "_script"=>[
                        "script"=> "Math.random()",
                        "type"=>"number",
                        "order"=> "asc"
                    ]
                ];
            }else{
                $so[] = [$key=>["order"=>$sort]];
            }
        }

        $this->sort = $so;
        return $this;
    }

    public function form(int $form)
    {
        $this->form = $form;
        return $this;
    }

    public function paginate(int $page, int $size)
    {
        $this->form = ($page - 1) * $size;
        $this->size = $size;
        return $this;
    }

    public function source(array $source)
    {
        $this->_source = $source;
        return $this;
    }

    public function paginateResult($retult)
    {
        $list = [];
        $total = 0;
        if(!empty($retult["hits"])){
            $hits = $retult["hits"];
            // total num
            if(!empty($hits['total']['value'])) {
                $total = $hits['total']['value'];
            }
            $hits = $hits["hits"];
            foreach ($hits as $hit){
                $_source = $hit['_source'];
                $_source['_id'] = $hit['_id'];
                $list[] = $_source;
            }
        }

        return [
            "total"=>$total,
            "page"=>($this->form /  $this->size) + 1,
            "size"=>$this->size,
            "total_page"=> ceil($total / $this->size),
            "list" => $list
        ];
    }

    public function result($query)
    {
        $query = $this->builder->getQuery();
        $params = [
            "index"=>$this->index,
            "body"=>[
                "query"=>[
                    "bool"=>$query
                ]
            ],
            "size"=>$this->size,
        ];

        if($this->form){
            $params['form'] = $this->form;
        }

        if($this->sort){
            $params['sort'] = $this->sort;
        }

        if($this->_source){
            $params['_source'] = $this->_source;
        }
        $search = $this->elasticsearch->search($params);
        $list = [];
        $total = 0;
        if(!empty($search["hits"])){
            $hits = $search["hits"];
            // total num
            if(!empty($hits['total']['value'])) {
                $total = $hits['total']['value'];
            }
            $hits = $hits["hits"];
            foreach ($hits as $hit){
                $_source = $hit['_source'];
                $_source['_id'] = $hit['_id'];
                $list[] = $_source;
            }
        }
        $this->total = $total;
        $this->list = $list;
        return $list;
    }
}
